// This 的觀念
var myName = '全域';
var person = {
myName: '小明',
getName: function () {
return this.myName;
}
};
var getName = person.getName;
console.log(getName());
// 印出來的值為何?
這段程式的重點就是函式調用的地方
那我們來看看執行的結果
這邊的關鍵點可以看到 console.log(getName());
這邊是用簡易呼叫的方式,所以自然他的 this 的綁定 會是 全域。
// bind 的其餘參數
var myName = '全域';
var obj = {
myName: '奇怪的函式',
fn: function (a, b, c) {
return this.myName + ',' + a + ',' + b +',' + c;
}
};
var fnA = obj.fn;
var fnB = fnA.bind(null, 0);
console.log(fnB(1, 2));
// console.log 會印出哪個答案
// 全域, 0, 1, 2
// 奇怪的函式, 0, 1, 2
// null, 0, 1, 2
// 奇怪的函式, 1, 2, undefined
主要的解題重點就是在於,如果在非嚴格模式(sloppy mode)下,利用bind/ call/ apply的this的指向帶入 null 或是 undefined 的話,會自動將 this 指向全域的 window 物件。
所以當然答案是全域,而且利用 bind 的方式多傳入了一個參數0,之後又再執行的時候才又傳入了參數1, 2,所以順序當然是0, 1, 2,最後的結果就是 全域, 0, 1, 2
。
延續上個問題喔,如果我們想要結果印出來是 null, 0, 1, 2的話該怎麼半?
很簡單喔~就只要讓函式執行的時候進入嚴格模式(strict mode)就好。
// bind 的其餘參數
var myName = '全域';
var obj = {
myName: '奇怪的函式',
fn: function (a, b, c) {
'use strict'; // <<<<<<<< 加入這段
return this + ',' + a + ',' + b +',' + c; // <<<<<< 移除myName的變數
}
};
var fnA = obj.fn;
var fnB = fnA.bind(null, 0);
console.log(fnB(1, 2));
// This 的觀念
var value = 'global';
var foo = {
value: 'local',
bar: function () {
return this.value;
}
};
// 直接執行
console.log(foo.bar());
// 賦值
console.log((foo.bar = foo.bar)());
// or
console.log((false || foo.bar)());
可以看到第一個 console.log(foo.bar());
是在 foo 的物件下執行 bar 這個 function,所以 this 的指向很明顯是 local。
再來第二個,console.log((foo.bar = foo.bar)());
利用 = 賦值運算子會回傳右邊的內容做為回傳值,在這邊就是回傳了右邊的 foo.bar,那麼這樣取出來的其實就是函式本身,之後又在外層有一個括號的運算子,後面又直接執行,這樣的狀況視為簡易呼叫的概念。
所以答案會是 global。
最後一個 or 的運算子,當左邊的運算元是 falsy 的結果的時候就會回傳右邊的運算元內容,所以狀況跟第二個一樣,也是回傳右邊的 foo.bar 的 function,那麼答案自然也是 global。
// Callback Function
var arr = ['1', '2', '3'].map(parseInt);
console.log(arr);
// [1, 2, 3]
// [undefined, undefined, undefined]
// [1, NaN, NaN]
// [1, undefined, undefined]
我們先來看看結果是
好,我們先分別來看看 map()
以及 parseInt()
這兩個方法是甚麼
map()
map 就是會依序把陣列的每個項目運算過後,並回傳一個新的 arr 陣列
var arr = ['1', '2', '3'].map(function (item) {
console.log(item);
return 'a' + item;
});
parseInt()
也就是說,parseInt() 第一個參數是要轉換成數字的字串,第二個參數是要用多少的進位數,如果都不設定,預設是 10 進位。
var arr = ['1', '2', '3'].map(function (item) {
console.log(item);
return parseInt(item, 10);
});
講解完兩個方法之後我們來解析為什麼答案會是 [1, NaN, NaN]
主要的原因是 map 所帶入的 callback function 中,所帶入的參數不只有 item 一個
主要有
item => 當前的對象
index => 當前的對象在該陣列中的索引值
array => 這個陣列的本身
那麼我們來看看原本的程式碼是
// Callback Function
var arr = ['1', '2', '3'].map(parseInt);
console.log(arr);
但它其實相當於:
var arr = ['1', '2', '3'].map(function (item, index) {
return parseInt(item, index);
});
所以當 1 進去的時候,parseInt('1', 0); => 答案是 1
當 2 進去的時候,parseInt('2', 1); => 答案是 NaN
當 3 進去的時候,parseInt('3', 2); => 答案是 NaN
PS: 進為模式的觀念其實是這樣
當你是用 0 作為進位指定基數,它就會直接回傳你原本的值。
當你是用 1 作為進位指定基數,它就會直接回傳你NaN。
當你是用 2 作為進位指定基數,它就會依照你的0跟1字串來進行演算。
其他進位模式各位也可以試著練習看看喔,今天就先這樣~希望對大家有幫助~汪汪